From 2228415323cd9685e81b49de6176e66f0d214a73 Mon Sep 17 00:00:00 2001
From: Vid Čufar <32638301+cufarvid@users.noreply.github.com>
Date: Fri, 26 Jan 2024 16:27:34 +0100
Subject: Fix search functionality (#62)

* Improve README instructions for local setup

* Fix search functionality #61
- use 'includes' for expense filtering

* Ensure expense groups with no matching expenses are hidden after filtering

* Improve README instructions for local setup
---
 src/app/groups/[groupId]/expenses/expense-list.tsx | 142 ++++++++++-----------
 1 file changed, 68 insertions(+), 74 deletions(-)

(limited to 'src/app/groups/[groupId]/expenses/expense-list.tsx')

diff --git a/src/app/groups/[groupId]/expenses/expense-list.tsx b/src/app/groups/[groupId]/expenses/expense-list.tsx
index b083ab6..0dc7a7e 100644
--- a/src/app/groups/[groupId]/expenses/expense-list.tsx
+++ b/src/app/groups/[groupId]/expenses/expense-list.tsx
@@ -92,8 +92,15 @@ export function ExpenseList({
     <>
       <SearchBar onChange={(e) => setSearchText(e.target.value)} />
       {Object.values(EXPENSE_GROUPS).map((expenseGroup: string) => {
-        const groupExpenses = groupedExpensesByDate[expenseGroup]
+        let groupExpenses = groupedExpensesByDate[expenseGroup]
         if (!groupExpenses) return null
+
+        groupExpenses = groupExpenses.filter(({ title }) =>
+          title.toLowerCase().includes(searchText.toLowerCase()),
+        )
+
+        if (groupExpenses.length === 0) return null
+
         return (
           <div key={expenseGroup}>
             <div
@@ -103,83 +110,70 @@ export function ExpenseList({
             >
               {expenseGroup}
             </div>
-            {groupExpenses
-              .filter(
-                (exp) =>
-                  exp.title.toLowerCase().match(searchText.toLowerCase()) !==
-                  null,
-              )
-              .map((expense: any) => (
-                <div
-                  key={expense.id}
-                  className={cn(
-                    'flex justify-between sm:mx-6 px-4 sm:rounded-lg sm:pr-2 sm:pl-4 py-4 text-sm cursor-pointer hover:bg-accent gap-1 items-stretch',
-                    expense.isReimbursement && 'italic',
-                  )}
-                  onClick={() => {
-                    router.push(
-                      `/groups/${groupId}/expenses/${expense.id}/edit`,
-                    )
-                  }}
-                >
-                  <CategoryIcon
-                    category={expense.category}
-                    className="w-4 h-4 mr-2 mt-0.5 text-muted-foreground"
-                  />
-                  <div className="flex-1">
-                    <div
-                      className={cn(
-                        'mb-1',
-                        expense.isReimbursement && 'italic',
-                      )}
-                    >
-                      {expense.title}
-                    </div>
-                    <div className="text-xs text-muted-foreground">
-                      Paid by{' '}
-                      <strong>{getParticipant(expense.paidById)?.name}</strong>{' '}
-                      for{' '}
-                      {expense.paidFor.map((paidFor: any, index: number) => (
-                        <Fragment key={index}>
-                          {index !== 0 && <>, </>}
-                          <strong>
-                            {
-                              participants.find(
-                                (p) => p.id === paidFor.participantId,
-                              )?.name
-                            }
-                          </strong>
-                        </Fragment>
-                      ))}
-                    </div>
+            {groupExpenses.map((expense: any) => (
+              <div
+                key={expense.id}
+                className={cn(
+                  'flex justify-between sm:mx-6 px-4 sm:rounded-lg sm:pr-2 sm:pl-4 py-4 text-sm cursor-pointer hover:bg-accent gap-1 items-stretch',
+                  expense.isReimbursement && 'italic',
+                )}
+                onClick={() => {
+                  router.push(`/groups/${groupId}/expenses/${expense.id}/edit`)
+                }}
+              >
+                <CategoryIcon
+                  category={expense.category}
+                  className="w-4 h-4 mr-2 mt-0.5 text-muted-foreground"
+                />
+                <div className="flex-1">
+                  <div
+                    className={cn('mb-1', expense.isReimbursement && 'italic')}
+                  >
+                    {expense.title}
                   </div>
-                  <div className="flex flex-col justify-between items-end">
-                    <div
-                      className={cn(
-                        'tabular-nums whitespace-nowrap',
-                        expense.isReimbursement ? 'italic' : 'font-bold',
-                      )}
-                    >
-                      {currency} {(expense.amount / 100).toFixed(2)}
-                    </div>
-                    <div className="text-xs text-muted-foreground">
-                      {formatDate(expense.expenseDate)}
-                    </div>
+                  <div className="text-xs text-muted-foreground">
+                    Paid by{' '}
+                    <strong>{getParticipant(expense.paidById)?.name}</strong>{' '}
+                    for{' '}
+                    {expense.paidFor.map((paidFor: any, index: number) => (
+                      <Fragment key={index}>
+                        {index !== 0 && <>, </>}
+                        <strong>
+                          {
+                            participants.find(
+                              (p) => p.id === paidFor.participantId,
+                            )?.name
+                          }
+                        </strong>
+                      </Fragment>
+                    ))}
                   </div>
-                  <Button
-                    size="icon"
-                    variant="link"
-                    className="self-center hidden sm:flex"
-                    asChild
+                </div>
+                <div className="flex flex-col justify-between items-end">
+                  <div
+                    className={cn(
+                      'tabular-nums whitespace-nowrap',
+                      expense.isReimbursement ? 'italic' : 'font-bold',
+                    )}
                   >
-                    <Link
-                      href={`/groups/${groupId}/expenses/${expense.id}/edit`}
-                    >
-                      <ChevronRight className="w-4 h-4" />
-                    </Link>
-                  </Button>
+                    {currency} {(expense.amount / 100).toFixed(2)}
+                  </div>
+                  <div className="text-xs text-muted-foreground">
+                    {formatDate(expense.expenseDate)}
+                  </div>
                 </div>
-              ))}
+                <Button
+                  size="icon"
+                  variant="link"
+                  className="self-center hidden sm:flex"
+                  asChild
+                >
+                  <Link href={`/groups/${groupId}/expenses/${expense.id}/edit`}>
+                    <ChevronRight className="w-4 h-4" />
+                  </Link>
+                </Button>
+              </div>
+            ))}
           </div>
         )
       })}
-- 
cgit v1.3

